Skip to main content

Opinionated Framework - Models & Migrations


What you will learn#

  • How to set the database settings
  • how create models and migrations
  • how to use models to add, update, and delete records

Setup#

  • open up terminal in your django folder
  • activate your virtual environment source ./djangoenv/bin/activate
  • start a new project django-admin startproject seconddjango
  • create a new app django-admin startapp pets

Setting Up the Database Settings#

In Django all settings for your application are found in settings.py. Now for our local development we can use the default settings which will create an sqlite3 database in our project folder. For deployment to Heroku, we will use the django-heroku library which will configure all the settings for heroku for us.

settings.py

# Database# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {    'default': {        'ENGINE': 'django.db.backends.sqlite3',        'NAME': BASE_DIR / 'db.sqlite3',    }}

If deploying to other environments or if wanting to use a different database locally read the django database documentation

Guide for Using DB URIs with Django

Django by default has some user and groups models we can migrate right away which will create our sqlite3 database.

In django migrations are created based on our models, migrations are used to create, alter and destroy database tables as our project evolves

python manage.py migrate

You should now see a db.sqlite3 file in your project, that's your development database.

Models and Migrations#

To add more tables to our database we need to:

  • create the model in an installed app
  • make our migrations
  • run our migrations

Installing our pets app#

Head over and install the pets app in seconddjango/settings.py


INSTALLED_APPS = [    'django.contrib.admin',    'django.contrib.auth',    'django.contrib.contenttypes',    'django.contrib.sessions',    'django.contrib.messages',    'django.contrib.staticfiles',    'pets.apps.PetsConfig']

and comment out the csrf middleware

MIDDLEWARE = [    'django.middleware.security.SecurityMiddleware',    'django.contrib.sessions.middleware.SessionMiddleware',    'django.middleware.common.CommonMiddleware',    # 'django.middleware.csrf.CsrfViewMiddleware',    'django.contrib.auth.middleware.AuthenticationMiddleware',    'django.contrib.messages.middleware.MessageMiddleware',    'django.middleware.clickjacking.XFrameOptionsMiddleware',]

Making a Model#

In your app folder should be a models.py, this is where we should make our models which are classes that specify the properties of the model.

#The Model class we will inherit fromfrom django.db import models
#new model classclass Turtle(models.Model):    # define a string field of max 100 characters    name = models.CharField(max_length=100)    # define a age that is an integer    age = models.IntegerField()

Making a Migration#

Now we run the makemigrations command which will read all our models and look for any changes since the last time it was ran. If it sees any changes (new models, modified models, removed models) it will create the migration files needed to apply those changes.

Once the migrations have been generated we can then run migrate again to update the database.

  • python manage.py makemigrations

  • python manage.py migrate

Using the Model#

Now that we have created the model let's learn how to use by practicing using it in the python shell.

  • run the command python manage.py shell this will open up the python shell (just type exit() if you need to exit at any time)

  • import our model so we can use it from pets.models import Turtle

  • Django Querying Docs

  • Django QuerySet Docs

Adding a turtle#

Every Django model has a "Objects Manager" object built into it that let's you query the database accessible at Model.objects.

  • create a Turtle Turtle.objects.create(name="Wilbert", age=5)
  • create 3 more turtles

Getting all the turtles#

Whenever we query the database we will get back a QuerySet object.

  • save all objects in a variable all = Turtle.objects.all()

  • access the first object all[0]

  • access the first objects name property all[0].name

Getting just one turtle#

Let's grab one turtle

  • wilbert = Turtle.objects.get(id=1)

  • wilbert.name

  • wilbert.age

Updating a Turtle#

Once we query a Turtle we can update them!

  • modify the object we retrieved wilbert.name = "Dilbert"

  • commit the changes to the database wilbert.save()

  • confirm the change was made wilbert.name

Deleting a Turtle#

  • wilbert.delete()

  • confirm deletion Turtle.objects.get(id=1).name

Using your model in a view#

Headover to pets/views.py and let's write a view using our model!

Make sure to copy over your helpers.py from this morning into your pets app


from django.shortcuts import render## For sending JSON Responsesfrom django.http import JsonResponse## To serialize objects into json stringsfrom django.core.serializers import serialize## To turn json strings into dictionariesimport json## The Turtle Modelfrom .models import Turtle## View classfrom django.views import View## GetBodyfrom .helpers import GetBody
# class for "/turtle" routesclass TurtleView(View):    ## Route to get all Turtles    def get(self, request):        ## get all the Turtles        all = Turtle.objects.all()        ## Turn the object into a json string        serialized = serialize("json", all)        ## Turn the json string into a dictionary        finalData = json.loads(serialized)        ## Send json response, turn safe off to avoid errors        return JsonResponse(finalData, safe=False)
    ## Route to create a turtle    def post (self, request):        ## get data from the body        body = GetBody(request)        print(body)        ## create new turtle        turtle = Turtle.objects.create(name=body["name"], age=body["age"])        ## turn the new turtle into json string then a dictionary        finalData = json.loads(serialize("json", [turtle])) #turtle in array to be serializable        ## Send json response        return JsonResponse(finalData, safe=False)

connect your class to a url


from django.contrib import adminfrom django.urls import pathfrom pets.views import TurtleView
urlpatterns = [    path('admin/', admin.site.urls),    path('turtle/', TurtleView.as_view())]
  • test out the routes then let's add some more!
# class for "/turtle/<id>" routesclass TurtleViewID(View):    ## Function to show 1 Turtle    def get (self, request, id):        ## get the turtle        turtle = Turtle.objects.get(id=id)        ## serilize then turn into dictionary        finalData = json.loads(serialize("json", [turtle]))        ## send json response        return JsonResponse(finalData, safe=False)
    ## Function for updating turtle    def put (self, request, id):        ## get the body        body = GetBody(request)        ##update turtle        ## ** is like JS spread operator        Turtle.objects.filter(id=id).update(**body)        ## query for turtle        turtle = Turtle.objects.get(id=id)        ## serialize and make dict        finalData = json.loads(serialize("json", [turtle]))        ## return json data        return JsonResponse(finalData, safe=False)
    def delete (self, request, id):        ## query the turtle        turtle = Turtle.objects.get(id=id)        ## delete the turtle        turtle.delete()        ## serilize and dict updated turtle        finalData = json.loads(serialize("json", [turtle]))        ##send json response        return JsonResponse(finalData, safe=False)

connect a URL

from django.contrib import adminfrom django.urls import pathfrom pets.views import TurtleView, TurtleViewID
urlpatterns = [    path('admin/', admin.site.urls),    path('turtle/', TurtleView.as_view()),    path('turtle/<id>/', TurtleViewID.as_view())]

You've created a full crud api! It's not perfect but tomorrow we'll introduce the djangorestframework to make this a bit simpler and smoother!


Resources to Learn More#